﻿Namespace ExecutableImageOperations
    ''' <summary>
    ''' DLL Unpacker Coapplication
    ''' </summary>
    ''' <remarks>Will unpack all user required Dlls on the directory where the Executable Assembly is located. Application will end if this procedure fails</remarks>
    Module Unpacker
        ''' <summary>
        ''' Will unpack all user Dlls required for this application to run, to the directory where the Executable Assembly is located
        ''' </summary>
        ''' <remarks>Application will end if this procedure fails</remarks>
        Public Sub Unpack()
            If CurrentConfiguration.UseExternalApi Then
                AddLogV("Using external ArpsEngine.dll API")
                Exit Sub
            End If
            If Not CurrentConfiguration.Standalone Then
                AddLog("WARNING: Cant use internal APIs since this assembly is not Standalone!")
                AddLog("         Forcing External APIs, make sure they are correctly installed.")
                CurrentConfiguration.UseExternalApi = True
                Exit Sub
            End If

            AddLogV("   *** DLL UNPACKER ***")

            Dim fs As New IO.FileStream(System.Reflection.Assembly.GetExecutingAssembly().Location, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
            Dim arphoonAddress As Integer
            Dim arphoonSize As Integer
            Dim arphoonHash(15) As Byte
            Dim md5 As New System.Security.Cryptography.MD5CryptoServiceProvider

            Try
                AddLogV("Reading assembly...")
                Dim buffer(23) As Byte
                fs.Seek(-30, IO.SeekOrigin.End)
                fs.Read(buffer, 0, buffer.Length)

                arphoonAddress = BitConverter.ToInt32(buffer, 0)
                arphoonSize = BitConverter.ToInt32(buffer, 4)

                Array.ConstrainedCopy(buffer, 8, arphoonHash, 0, 16)

                Dim hash() As Byte
                Dim fsout As IO.FileStream

                AddLogV("Unpacking ArpsEngine.dll...")

                Erase buffer
                fs.Seek(arphoonAddress, IO.SeekOrigin.Begin)
                ReDim buffer(arphoonSize - 1)
                fs.Read(buffer, 0, buffer.Length)
                hash = md5.ComputeHash(buffer)
                If CompareArrays(hash, arphoonHash) Then
                    fsout = New IO.FileStream(".\ArpsEngine.dll", IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None)
                    fsout.Write(buffer, 0, buffer.Length)
                    fsout.Close()
                    fsout.Dispose()
                    fsout = Nothing
                Else
                    AddLog("WARNING: Packed ArpsEngine.dll is damaged. Trying to use external one.")
                End If
            Catch ex As Exception
                AddLog("ERROR: Cant unpack internal DLLs. Trying to use External ones.")
                AddLogV("   ex: " & ex.Message)
                CurrentConfiguration.UseExternalApi = True
                fs.Close()
                fs.Dispose()
                fs = Nothing
                Exit Sub
            End Try

            fs.Close()
            fs.Dispose()
            fs = Nothing

            AddLogV("   *** DLL UNPACKER DONE ***")
        End Sub

        Private Function CompareArrays(ByRef arrayA() As Byte, ByRef arrayB() As Byte) As Boolean
            If Not arrayA.Length = arrayB.Length Then Return False

            Dim i As Integer
            For i = 0 To arrayA.Length - 1
                If Not arrayA(i) = arrayB(i) Then Return False
            Next

            Return True
        End Function
    End Module
End Namespace

